package ru.nlezhnev.data_models;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import ru.nlezhnev.utils.ASObjectUtils;
import ru.nlezhnev.utils.MapUtils;
import ru.nlezhnev.utils.PhpDecoder;
import ru.nlezhnev.utils.PhpEncoder;
import flex.messaging.io.amf.ASObject;

public class FarmDataModel {
	final static private String[] INCOMING_ACTIONS_PATH = {"farm_data", "actions", "incoming"};
	final static private String GET_DATA_SQL = "SELECT `vkontact_id`, `common`, `farm_data`, `friends_data`, `patch_version` FROM `farm_data` WHERE `vkontact_id` = ?";
	final static private String SET_DATA_SQL = "UPDATE `farm_data` SET `common` = ?, `farm_data` = ? WHERE `vkontact_id` = ?";
	//final static private String COPY_DATA_SQL = "INSERT INTO `farm_data` SELECT ?, `common`, `farm_data`, `friends_data`, `patch_version` FROM `farm_data` WHERE `vkontact_id` = 0";
	final static private String INSERT_DATA_SQL = "INSERT INTO `farm_data` (`vkontact_id`, `common`, `farm_data`, `friends_data`, `farm_data_bcp`) VALUES (?, ?, ?, '', '')";
	
	private Connection conn;
	private int uid;
	private ASObject data;
		
	public FarmDataModel(Connection conn, int uid) {
		this.conn = conn;
		this.uid = uid;
		resetData();
		initData(uid);
		addIncomingActions();
	}
	
	@SuppressWarnings("unchecked")
	private void resetData() {
		data = new ASObject();
		data.put("farm_data", new ASObject());
		data.put("common", new ASObject());
		data.put("friends_data", new ASObject());
	}
	
	private	void addIncomingActions() {
		FarmActionsModel farmActions = new FarmActionsModel(conn, uid);		
		ASObject actions = ASObjectUtils.makeByPath(INCOMING_ACTIONS_PATH, farmActions.getActions());
		MapUtils.merge(data, actions);
	}	
	
	public ASObject getData() {
		return data;
	}
	
	public void save() {
		try {
			PreparedStatement pstmt = conn.prepareStatement(SET_DATA_SQL);
			String commonSerialized = PhpEncoder.serialize(data.get("common"));
			String farmDataSerialized = PhpEncoder.serialize(data.get("farm_data"));
			pstmt.setString(1, commonSerialized);
			pstmt.setString(2, farmDataSerialized);
	        pstmt.setInt(3, uid);
	        pstmt.executeUpdate();
	        pstmt.close();
	        //saveBinaryTest();
		} catch (SQLException e) {
			System.out.println("Can't save data uid #" + uid + " " + e.getMessage());
			resetData();
		}
	}
	
//	private void saveBinaryTest() throws SQLException {
//		try {
//			long dataId = DataSaver.writeJavaObject(conn, data);
//			DataSaver.readJavaObject(conn, dataId);
//		} catch (Exception e) {
//			System.out.println("Can't save binary data uid #" + uid + " " + e.getMessage());
//		}
//	}
	
	@SuppressWarnings("unchecked")
	private void initData(int userId) {
		try {
			PreparedStatement pstmt = conn.prepareStatement(GET_DATA_SQL);
	        pstmt.setInt(1, userId);
	        ResultSet rs = pstmt.executeQuery();
	        if (rs.next()) {
	    		for (Object key : data.keySet()) {
	    			Object fieldValue = null;
	    			String phpString = rs.getString((String)key);
	    			if (phpString != "") {
	    				fieldValue = PhpDecoder.decode(phpString);
	    			}
    				if (fieldValue != null) {
    					data.put(key, fieldValue);
    				}
	    		}
	        } else if (userId != 0) {
	        	loadDefaultData();
	        	makeNewUser();
	        } else {
	        	System.out.println("Can't load default user, check row 0 in table farm_data");
	        }
	        pstmt.close();
	        rs.close();
		} catch(SQLException e) {			
			System.out.println("Can't load data uid #" + uid + " " + e.getMessage());			
			resetData();
		}
		
		FarmActionsModel farmActions = new FarmActionsModel(conn, uid);
		String[] path = {"farm_data", "actions", "incoming"};
		ASObject actions = ASObjectUtils.makeByPath(path, farmActions.getActions());
		MapUtils.merge(data, actions);
	}
	
	private void makeNewUser() {
		try {
			PreparedStatement pstmt = conn.prepareStatement(INSERT_DATA_SQL);			
			String commonSerialized = PhpEncoder.serialize(data.get("common"));
			String farmDataSerialized = PhpEncoder.serialize(data.get("farm_data"));
			pstmt.setInt(1, uid);
			pstmt.setString(2, commonSerialized);
			pstmt.setString(3, farmDataSerialized);
			pstmt.executeUpdate();
			pstmt.close();
		} catch (SQLException e) {
			System.out.println("Can't copy data from uid# 0 to uid#" + uid + ": " + e.getMessage());
		}
	}
	
	private void loadDefaultData() {
		initData(0);
	}
}
